﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// Zip压缩解压帮助类
    /// </summary>
    public class ZipHelper
    {
        #region 方法
        /// <summary>
        /// Zip压缩文件
        /// </summary>
        /// <param name="outPath">输出物理路径</param>
        /// <param name="fileName">压缩文件相对目录</param>
        /// <param name="fileSource">源文件路径</param>
        public static void FileZip(string outPath, string fileName, string fileSource)
        {
            using FileStream zipFileToOpen = new(outPath, FileMode.OpenOrCreate);
            using ZipArchive archive = new(zipFileToOpen, ZipArchiveMode.Update);
            fileName = fileName.Trim(Path.DirectorySeparatorChar);
            CreateZipFile(fileSource, fileName, archive);
        }

        /// <summary>
        /// Zip压缩文件
        /// </summary>
        /// <param name="outPath">输出物理路径</param>
        /// <param name="files">源文件</param>
        public static void FilesZip(string outPath, params string[] files)
        {
            using FileStream zipFileToOpen = new(outPath, FileMode.OpenOrCreate);
            using ZipArchive archive = new(zipFileToOpen, ZipArchiveMode.Update);
            foreach (var file in files)
            {
                //string fileName = file.Replace(AppConsts.ServerUpdateFile + Path.DirectorySeparatorChar, "");
                string fileName = file.Trim(Path.DirectorySeparatorChar);
                CreateZipFile(file, fileName, archive);
            }
        }

        /// <summary>
        /// Zip压缩文件夹
        /// </summary>
        /// <param name="outPath">输出物理路径</param>
        /// <param name="directory">源文件夹</param>
        public static void DirectoryZip(string outPath, string directory)
        {
            string[] allFiles = Directory.GetFiles(directory, "", SearchOption.AllDirectories);
            using FileStream zipFileToOpen = new(outPath, FileMode.OpenOrCreate);
            using ZipArchive archive = new(zipFileToOpen, ZipArchiveMode.Update);
            foreach (var file in allFiles)
            {
                //获取压缩文件相对目录
                string fileName = file.Replace(directory + Path.DirectorySeparatorChar, "");
                CreateZipFile(file, fileName, archive);
            }
        }

        /// <summary>
        /// 解压文件到指定目录
        /// </summary>
        /// <param name="outPath">输出物理路径</param>
        /// <param name="zipPath">源压缩文件路径</param>
        /// <param name="overwriteFiles">重写文件</param>
        public static void UnZip(string outPath, string zipPath, bool overwriteFiles = true)
        {
            if (!Directory.Exists(outPath))
            {
                Directory.CreateDirectory(outPath);
            }
            using FileStream zipFileToOpen = new(zipPath, FileMode.Open);
            using ZipArchive archive = new(zipFileToOpen, ZipArchiveMode.Read);
            archive.ExtractToDirectory(outPath, overwriteFiles);
        }

        /// <summary>
        /// 解压文件到指定目录
        /// </summary>
        /// <param name="outPath">输出物理路径</param>
        /// <param name="zipStream">源压缩文件流</param>
        /// <param name="overwriteFiles">重写文件</param>
        public static void UnZip(string outPath, Stream zipStream, bool overwriteFiles = true)
        {
            if (!Directory.Exists(outPath))
            {
                Directory.CreateDirectory(outPath);
            }
            zipStream.Seek(0, SeekOrigin.Begin); // 设置当前流的位置为流的开始

            using ZipArchive archive = new(zipStream, ZipArchiveMode.Read);
            archive.ExtractToDirectory(outPath, overwriteFiles);

            zipStream.Seek(0, SeekOrigin.Begin);   // 设置当前流的位置为流的开始
        }

        #endregion

        #region 私有方法
        /// <summary>
        /// 生成压缩文件
        /// </summary>
        /// <param name="fileSource">源文件</param>
        /// <param name="fileName">压缩文件相对目录</param>
        /// <param name="archive">压缩文件包</param>
        private static void CreateZipFile(string fileSource, string fileName, ZipArchive archive)
        {
            ZipArchiveEntry readMeEntry = archive.CreateEntry(fileName);
            readMeEntry.LastWriteTime = File.GetLastWriteTime(fileSource);
            using Stream stream = readMeEntry.Open();
            byte[] bytes = File.ReadAllBytes(fileSource);
            stream.Write(bytes, 0, bytes.Length);
        }

        #endregion

    }

}
